package com.simple.mqtt.server.channel;

import com.simple.mqtt.common.tool.LogTool;
import com.simple.mqtt.server.config.MqttBrokerConfig;
import com.simple.mqtt.server.domain.ClientInfo;
import io.netty.channel.ChannelHandlerContext;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Channel manager
 * Manages client connections and channel lifecycle
 */
public class ChannelManager {
    private final ConcurrentMap<String, ChannelHandlerContext> channelMap = new ConcurrentHashMap<>();

    /**
     * Add channel for client
     * @param clientId client ID
     * @param context channel context
     */
    public void addChannel(String clientId, ChannelHandlerContext context) {
        ChannelHandlerContext oldContext = channelMap.put(clientId, context);
        if (oldContext != null && oldContext != context) {
            LogTool.warn("Client {} already connected, closing old connection", clientId);
            oldContext.close();
        }
    }

    /**
     * Remove channel for client
     * @param clientId client ID
     */
    public void removeChannel(String clientId) {
        channelMap.remove(clientId);
    }

    /**
     * Get channel for client
     * @param clientId client ID
     * @return channel context or null if not found
     */
    public ChannelHandlerContext getChannel(String clientId) {
        return channelMap.get(clientId);
    }

    /**
     * Get all connected clients
     * @param config broker configuration
     * @return list of client information
     */
    public List<ClientInfo> getAllClients(MqttBrokerConfig config) {
        List<ClientInfo> clients = new ArrayList<>();
        for (ChannelHandlerContext context : channelMap.values()) {
            if (context.channel().isActive()) {
                clients.add(ClientInfo.from(context, config));
            }
        }
        return clients;
    }

    /**
     * Get all active channels
     * @return list of active channel contexts
     */
    public List<ChannelHandlerContext> getAllActiveChannels() {
        List<ChannelHandlerContext> activeChannels = new ArrayList<>();
        for (ChannelHandlerContext context : channelMap.values()) {
            if (context.channel().isActive()) {
                activeChannels.add(context);
            }
        }
        return activeChannels;
    }

    /**
     * Get active connection count
     * @return number of active connections
     */
    public int getConnectionCount() {
        return (int) channelMap.values().stream()
                .filter(ctx -> ctx.channel().isActive())
                .count();
    }
}
